package com.kingray.openfire.plugin.servlet;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jivesoftware.admin.AuthCheckFilter;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.user.User;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.packet.Presence;

import com.kingray.openfire.plugin.KingrayServicePlugin;

public class PresenceServiceServlet extends HttpServlet {
	public static final String STATUS_IMAGE_REQUEST_PATH = KingrayServicePlugin.PLUGIN_BASE_REQUEST
			+ "presenceservice?actionType=getStatusImageByShow";

	public static final Logger log = LoggerFactory
			.getLogger(PresenceServiceServlet.class);
	private byte available[];
	private byte away[];
	private byte chat[];
	private byte dnd[];
	private byte offline[];
	private byte xa[];

	private Map<String, byte[]> imageCache = new HashMap<String, byte[]>();
	private Map<String, String> imageTypeCache = new HashMap<String, String>();

	@Override
	public void init(ServletConfig servletConfig) throws ServletException {
		super.init(servletConfig);
		available = loadResource("/images/status/user-green-16x16.gif");
		away = loadResource("/images/status/user-yellow-16x16.gif");
		chat = loadResource("/images/status/user-green-16x16.gif");
		dnd = loadResource("/images/status/user-red-16x16.gif");
		offline = loadResource("/images/status/user-clear-16x16.gif");
		xa = loadResource("/images/status/user-yellow-16x16.gif");
		// Exclude this servlet from requering the user to login
		AuthCheckFilter.addExclude("kingrayplugin/presenceservice");
	}

	@Override
	public void destroy() {
		super.destroy();
		available = null;
		away = null;
		chat = null;
		dnd = null;
		offline = null;
		xa = null;
		AuthCheckFilter.removeExclude("kingrayplugin/presenceservice");
	}

	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		this.doPost(request, response);
	}

	@Override
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		String actionType = request.getParameter("actionType");
		if (actionType != null) {
			if ("getStatusImageByShow".equals(actionType)) {
				doGetStatusImageByShow(request, response);
			}
		} else {
			printException(response,
					"ParameterException: Please use \" actionType \" instead.");
		}
	}

	private void printException(HttpServletResponse response, String exception)
			throws ServletException, IOException {
		response.setContentType("text/plain");
		PrintWriter out = response.getWriter();
		StringBuilder builder = new StringBuilder();
		builder.append(exception);
		out.print(builder.toString());
		out.flush();
		out.close();
	}

	protected void doGetStatusImageByUserName(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		String userName = request.getParameter("userName");
		if (userName != null) {
			try {
				User user = XMPPServer.getInstance().getUserManager()
						.getUser(userName);
				if (user != null) {
					Presence presence = XMPPServer.getInstance()
							.getPresenceManager().getPresence(user);
					if (presence == null) {
						writeImageContent(request, response, "offline", offline);
					} else if (presence.getShow() == null) {
						writeImageContent(request, response, "available",
								available);
					} else if (presence.getShow().equals(
							org.xmpp.packet.Presence.Show.away)) {
						writeImageContent(request, response, "away", away);
					} else if (presence.getShow().equals(
							org.xmpp.packet.Presence.Show.chat)) {
						writeImageContent(request, response, "chat", chat);
					} else if (presence.getShow().equals(
							org.xmpp.packet.Presence.Show.dnd)) {
						writeImageContent(request, response, "dnd", dnd);
					} else if (presence.getShow().equals(
							org.xmpp.packet.Presence.Show.xa)) {
						writeImageContent(request, response, "xa", xa);
					}
				} else {
					printException(response, "UserNotExistsException");
				}
			} catch (UserNotFoundException e) {
				e.printStackTrace();
			}
		} else {
			printException(response, "LoseRequiredParameterUserName");
		}
	}

	protected void doGetStatusImageByShow(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		String show = request.getParameter("show");
//		System.out.println("show ====================== " + show);
		if (show == null) {
			writeImageContent(request, response, "available", available);
		} else if ("offline".equals(show)) {
			writeImageContent(request, response, "offline", offline);
		} else if (show.equals(org.xmpp.packet.Presence.Show.away.toString())) {
			writeImageContent(request, response, "away", away);
		} else if (show.equals(org.xmpp.packet.Presence.Show.chat.toString())) {
			writeImageContent(request, response, "chat", chat);
		} else if (show.equals(org.xmpp.packet.Presence.Show.dnd.toString())) {
			writeImageContent(request, response, "dnd", dnd);
		} else if (show.equals(org.xmpp.packet.Presence.Show.xa.toString())) {
			writeImageContent(request, response, "xa", xa);
		} else if (show.equals("available")) {
			writeImageContent(request, response, "available", available);
		} else {
			printException(response, "PresenceShowNameNotExists");
		}
	}

	private void writeImageContent(HttpServletRequest request,
			HttpServletResponse response, String presenceType,
			byte[] defaultImage) throws IOException {
		// String images = request.getParameter("images");
		// if (request.getParameter(presenceType) != null) {
		// writeImageContent(request.getParameter(presenceType), defaultImage,
		// response);
		// } else if (images != null) {
		// response.sendRedirect(images.replace("--IMAGE--", presenceType));
		// } else {
		// writeImageContent(null, defaultImage, response);
		// }
		writeImageContent(null, defaultImage, response);
	}

	private void writeImageContent(String url, byte[] defaultContent,
			HttpServletResponse response) throws IOException {
		ServletOutputStream os = response.getOutputStream();
		byte[] imageContent = defaultContent;
		String contentType = "image/gif";
		if (url != null) {
			try {
				byte[] cachedContent = imageCache.get(url);
				if (cachedContent == null) {
					URLConnection connection = new URL(url).openConnection();
					InputStream in = connection.getInputStream();
					ByteArrayOutputStream bytes = new ByteArrayOutputStream();
					byte buffer[] = new byte[1024 * 4];
					int last_read_bytes = 0;
					while ((last_read_bytes = in.read(buffer)) != -1) {
						bytes.write(buffer, 0, last_read_bytes);
					}
					if (bytes.size() > 0) {
						imageCache.put(url, bytes.toByteArray());
						imageTypeCache.put(url, connection.getContentType());
					}
				}
				if (imageTypeCache.get(url) != null) {
					contentType = imageTypeCache.get(url);
					imageContent = imageCache.get(url);
				}
			} catch (IOException e) {
				log.error(e.getMessage(), e);
			}
		}
		response.setContentType(contentType);
		// response.setContentType("application/octet-stream");
		os.write(imageContent);
		os.flush();
		os.close();
	}

	/**
	 * 加载资源
	 * 
	 * @param path
	 * @return
	 */
	private byte[] loadResource(String path) {
//		ServletContext context = getServletContext();
		InputStream in = PresenceServiceServlet.class.getResourceAsStream(path);
		if (in == null) {
			log.error("error loading:" + path);
			return null;
		}
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		try {
			for (int i = in.read(); i > -1; i = in.read()) {
				out.write(i);
			}
		} catch (IOException e) {
			log.error("error loading:" + path);
		}
		return out.toByteArray();
	}

	public static void main(String[] args) {
//		new PresenceServiceServlet()
//				.loadResource("/images/status/user-green-16x16.gif");
		PresenceServiceServlet test = new PresenceServiceServlet();
		InputStream in = PresenceServiceServlet.class.getResourceAsStream("/images/status/user-green-16x16.gif");
		System.out.println(in);
	}
}
